<?php

namespace LaiHe\LaravelHelper;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\Resource;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class LaravelHelperServiceProvider extends ServiceProvider
{
	public function boot()
	{
		$this->extendResponse();
	}

	public function register()
	{
	}

	/**
	 * 扩展response方法
	 */
	private function extendResponse()
	{
		Resource::withoutWrapping();//fix 资源格式
		Response::macro('success', [$this, 'responseSuccess']);
		Response::macro('table', [$this, 'responseTable']);
		Response::macro('error', [$this, 'responseError']);
	}

	/**
	 * 返回layui-table数据
	 * @param \Illuminate\Pagination\LengthAwarePaginator|\Illuminate\Support\Collection|\Illuminate\Contracts\Support\Responsable|array $data 数据
	 *
	 * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
	 */
	public function responseTable($data = [])
	{
		$data = $this->parseData($data);
		if(empty($data['meta'])){
			$count = empty($data['data']) ? 0 : 1;
			$data  = empty($data['data']) ? [] : $data['data'];
		}else{
			$count = $data['meta']['total'];
			$data  = $data['data'];
		}

		return Response::json([
			'code'    => 0,
			'message' => '数据获取成功',
			'count'   => $count,
			'data'    => $data,
		], 200, [], JSON_UNESCAPED_UNICODE);
	}

	/**
	 * 成功返回
	 *
	 * @param array|string $data     数据，字符串时转为提示消息
	 * @param string       $message  提示消息
	 * @param null         $redirect 跳转地址
	 * @param null         $lang     接口当前使用的语言
	 *
	 * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
	 */
	public function responseSuccess($data = [], $message = '操作成功', $redirect = null, $lang = null)
	{
		$redirect = $redirect ? URL::to($redirect) : '';
		$lang     = $lang ?: Config::get('app.locale');
		if(is_string($data)){
			$message = $data;
			$data    = [];
		}
		if(!Request::expectsJson() && empty($data) && View::exists('success')){
			return Response::view('success', ['message' => $message, 'redirect' => $redirect, 'lang' => $lang]);
		}
		$data = $this->parseData($data);

		return Response::json([
			'status'   => true,
			'code'     => 0,
			'message'  => (string)$message,
			'data'     => empty($data['meta']) ? $data['data'] : $data,
			'redirect' => $redirect,
			'lang'     => $lang,
		], 200, [], JSON_UNESCAPED_UNICODE);
	}

	/**
	 * 错误返回
	 *
	 * @param string          $message  提示消息
	 * @param string|int|null $redirect 跳转地址|错误码
	 * @param int             $code     错误码
	 * @param array           $data     数据
	 * @param null            $lang     接口当前使用的语言
	 *
	 * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
	 */
	public function responseError($message = '操作失败', $redirect = null, $code = 400, $data = [], $lang = null)
	{
		if(is_numeric($redirect)){
			$code     = $redirect;
			$redirect = null;
		}
		$redirect = $redirect ? URL::to($redirect) : '';
		$lang     = $lang ?: Config::get('app.locale');
		if(!Request::expectsJson() && empty($data) && View::exists('error')){
			return Response::view('error', ['message' => $message, 'code' => $code, 'redirect' => $redirect, 'lang' => $lang]);
		}
		$data = $this->parseData($data);

		return Response::json([
			'status'   => false,
			'code'     => $code,
			'message'  => (string)$message,
			'data'     => empty($data['meta']) ? $data['data'] : $data,
			'redirect' => $redirect,
			'lang'     => $lang,
		], 200, [], JSON_UNESCAPED_UNICODE);
	}


	/**
	 * @param mixed $data 数据
	 *
	 * @return array
	 */
	private function parseData($data)
	{
		$result = ['data' => [], 'meta' => []];
		if($data instanceof JsonResource){
			$resource = $data->response()->getData(true);
			//分页数据、单个数据、数据集合
			if(Arr::has($resource, ['data', 'links', 'meta']) && count(array_keys($resource)) == 3){
				$result['data'] = $resource['data'];
				$result['meta'] = $resource['meta'] + $resource['links'];
			}else{
				$result['data'] = $resource;
			}
		}else if($data instanceof LengthAwarePaginator){
			$resource       = $data->toArray();
			$result['data'] = $resource['data'];
			$result['meta'] = Arr::except($resource, ['data']);
		}else if($data instanceof Collection){
			$result['data'] = $data->toArray();
			$result['meta'] = ['total' => $data->count(),];
		}else{
			$result['data'] = toArray($data);
		}

		return $result;
	}
}